/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package concordion.plugin.maven;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.codehaus.doxia.sink.Sink;
import org.xml.sax.InputSource;

/**
 *
 * @author bangroot
 */
class ConcordionReports {

    File concordionDir;

    public ConcordionReports(File concordionDir) {
        this.concordionDir = concordionDir;
    }

    void generateReport(Sink sink, ResourceBundle bundle) {
        generateReport(sink, bundle, false);
    }

    void generateReport(Sink sink, ResourceBundle bundle, boolean createLinks) {
        if (concordionDir.exists() && concordionDir.isDirectory()) {
            File[] children = concordionDir.listFiles(new FilenameFilterImpl());
            if (0 == children.length) {
                sink.text(bundle.getString("concordion.summary.noreports"));
            } else {
                processChildren(children, sink, createLinks);
            }
        } else {
            sink.text(bundle.getString("concordion.summary.noreports"));
        }
    }

    private String findRelativeParentPath(File child) {
       String relative =
               concordionDir.toURI().relativize(child.getParentFile().toURI()).getPath();
       if (relative.endsWith("/")) {
           relative = relative.substring(0, relative.length()-1);
       }
       return relative;
    }

    private void processChildren(File[] children, Sink sink, boolean createLinks) {
        Arrays.sort(children, new Comparator<File>() {

            public int compare(File arg0, File arg1) {
                if (arg0.isFile() && arg1.isFile()) {
                    return arg0.getName().compareTo(arg1.getName());
                } else if (arg0.isDirectory() && arg1.isDirectory()) {
                    return arg0.getName().compareTo(arg1.getName());
                } else {
                    if (arg0.isFile()) {
                        return 1;
                    } else {
                        return -1;
                    }
                }
            }
        });
        boolean sectionStarted = false;
        boolean sectionEnded = false;
        for (File child : children) {
            String relative = findRelativeParentPath(child);
            if (child.isFile()) {
                if (!sectionStarted) {
                    sink.section2();
                    sink.sectionTitle2();
                    sink.text(relative.replaceAll("/", "."));
                    sink.sectionTitle2_();
                    sink.table();
                    sink.tableRow();
                    sink.tableHeaderCell();
                    sink.text("Specification");
                    sink.tableHeaderCell_();
                    sink.tableHeaderCell();
                    sink.text("Result");
                    sink.tableHeaderCell_();
                    sink.tableRow_();
                    sectionStarted = true;
                }
                sink.tableRow();
                sink.tableCell();
                if (createLinks) {
                    sink.rawText("<a href='concordion/" + relative + "/" + child.getName() + "' target='_blank'>");
                }
                sink.text(child.getName());
                if (createLinks) {
                    sink.rawText("</a>");
                }
                sink.tableCell_();
                sink.tableCell();
                if (passingFile(child)) {
                    sink.rawText("<span style='background-color: #afa !important;'>");
                    sink.text("Success");
                    sink.rawText("</span>");
                } else {
                    sink.rawText("<span style='background-color: #ffb0b0 !important;'>");
                    sink.text("Failed");
                    sink.rawText("</span>");
                }
                sink.tableCell_();
                sink.tableRow_();
            } else {
                if (sectionStarted && !sectionEnded) {
                    sink.table_();
                    sink.section2_();
                    sectionEnded = true;
                }
                processChildren(child.listFiles(new FilenameFilterImpl()), sink, createLinks);
            }
        }
        if (sectionStarted && !sectionEnded) {
            sink.table_();
            sink.section2_();
            sectionEnded = true;
        }
    }

    public boolean passingFile(File fileToEval) {
        try {
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expression = xpath.compile("//*[@class='failure']");
            InputSource xmlInput = new InputSource(new FileInputStream(fileToEval));
            String failures = expression.evaluate(xmlInput);
            return failures.equals("");
        } catch (XPathExpressionException ex) {
            return false;
        } catch (FileNotFoundException ex) {
            return false;
        }
    }

    private static class FilenameFilterImpl implements FileFilter {

        public FilenameFilterImpl() {
        }

        public boolean accept(File file) {
            if (file.isDirectory()) {
                return !file.getName().equals(".svn");
            } else {
                return file.getName().endsWith(".html");
            }
        }
    }
}
